package hotel.controller.room;

import javafx.fxml.FXML;

import javafx.scene.control.Button;

import javafx.scene.control.TextField;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.StringConverter;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Iterator;
import java.util.List;

import hotel.common.Comm;
import hotel.common.MsgBox;
import hotel.dao.HotelDao;
import hotel.modal.Room;
import hotel.modal.RoomReserve;
import hotel.modal.RoomType;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;

import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Control;
import javafx.scene.control.Spinner;
import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.control.DatePicker;

public class RoomReserveChangeController {
	@FXML
	private Label title;
	@FXML
	private TextField nameTextField;
	@FXML
	private Label reserveIdLabel;
	@FXML
	private TextField phoneTextField;
	@FXML
	private DatePicker startDatePicker;
	@FXML
	private Spinner<Integer> startTimeSpinner;
	@FXML
	private ComboBox<RoomType> roomTypeCb;
	@FXML
	private ComboBox<Room> roomCb;
	@FXML
	private Spinner<Integer> daySpinner;
	@FXML
	private TextField depositTextField;
	@FXML
	private Spinner<Integer> reserveTimeSpinner;
	@FXML
	private TextField commentTextField;
	@FXML
	private Button btnOk;
	@FXML
	private Button btnCancel;
	
	private RoomReserve roomReserve;
	private Room room;
	private int mode = 0;
	
	@FXML
	public void initialize() {
		initComponent();
		initData();
	}
	
	public void setInitData(RoomReserve roomReserve) {
		this.roomReserve = roomReserve;
		room = HotelDao.getRoom(roomReserve.getRoomNo());
		if(roomReserve == null || room == null) return; 
		
		reserveIdLabel.setText(roomReserve.getReserveId());
		roomTypeCb.getSelectionModel().select(findRoomTypeCbIndex(room));
		roomCb.getSelectionModel().select(findRoomCbIndex(room));
		nameTextField.setText(roomReserve.getName());
		phoneTextField.setText(roomReserve.getPhone());
		
		
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		LocalDate date = LocalDate.parse(roomReserve.getPresetTime(), formatter);
		LocalTime time = LocalTime.parse(roomReserve.getPresetTime(), formatter);
		startDatePicker.setValue(date);
		startTimeSpinner.getValueFactory().setValue(time.getHour());
		
		daySpinner.getValueFactory().setValue(roomReserve.getDuration());
		reserveTimeSpinner.getValueFactory().setValue(roomReserve.getHoldTime());
		depositTextField.setText(String.valueOf(roomReserve.getDeposit()));
		commentTextField.setText(roomReserve.getComment());
		
		roomReserve.setModified(false);
		
	}
	
	public void setReadMode() {
		this.mode = 1;
		title.setText("预定详情");
		setDisableComp(roomTypeCb);
		setDisableComp(roomCb);
		setDisableComp(nameTextField);
		setDisableComp(phoneTextField);
		setDisableComp(startDatePicker);
		setDisableComp(startTimeSpinner);
		setDisableComp(daySpinner);
		setDisableComp(reserveTimeSpinner);
		setDisableComp(depositTextField);
		setDisableComp(commentTextField);
	}
	
	private void setDisableComp(Control c) {
		c.setDisable(true);
		c.setStyle("-fx-opacity: 1; -fx-text-fill: grey; -fx-background-color: white;");
	}
	
	private void initData() {
		List<RoomType> list = runRoomTypeCbFilter(HotelDao.getAllRoomType());
		ObservableList<RoomType> roomTypeItems = roomTypeCb.getItems();
		roomTypeItems.addAll(list);
		if(list.size() > 0) roomTypeCb.getSelectionModel().select(0);
		
		LocalDate today = LocalDate.now();
		startDatePicker.setValue(today);
	}
	
	private void initComponent() {
		roomTypeCb.setCellFactory(new Callback<ListView<RoomType>, ListCell<RoomType>>() { // 下拉列表显示
			@Override
			public ListCell<RoomType> call(ListView<RoomType> p) {
				ListCell<RoomType> cell = new ListCell<RoomType>() {
					@Override
					protected void updateItem(RoomType item, boolean empty) {
						super.updateItem(item, empty);
						if (empty) {
							setText("");
						} else {
							if(item.isHourRoom()) setText(item.getTypeName() + "(钟点房)");
							else setText(item.getTypeName());
						}
					}
				};
				return cell;
			}
		});
		
		roomTypeCb.setButtonCell(new ListCell<RoomType>() {
			@Override
			protected void updateItem(RoomType item, boolean empty) {
				super.updateItem(item, empty);
				if (empty) {
					setText("");
				} else {
					if(item.isHourRoom()) setText(item.getTypeName() + "(钟点房)");
					else setText(item.getTypeName());
				}
			}
		});
	
		roomTypeCb.valueProperty().addListener(new ChangeListener<RoomType>() { // 房间类型ComBobox监听
			@Override
			public void changed(ObservableValue<? extends RoomType> observable, RoomType oldValue, RoomType newValue) {
				List<Room> rList = runRoomCbFilter(HotelDao.getRoomList(newValue)); // 从数据库拉取房间信息
				ObservableList<Room> obList = FXCollections.observableArrayList(rList);
				roomCb.setItems(obList);
				if(obList.size() > 0) roomCb.getSelectionModel().select(0);
			}
	    });
		
		roomCb.setCellFactory(new Callback<ListView<Room>, ListCell<Room>>() { // 下拉列表显示
			@Override
			public ListCell<Room> call(ListView<Room> p) {
				ListCell<Room> cell = new ListCell<Room>() {
					@Override
					protected void updateItem(Room item, boolean empty) {
						super.updateItem(item, empty);
						if (empty) {
							setText("");
						} else {
							setText(item.getRoomNo());
						}
					}
				};
				return cell;
			}
		});
		
		roomCb.setButtonCell(new ListCell<Room>() {
			@Override
			protected void updateItem(Room item, boolean empty) {
				super.updateItem(item, empty);
				if (empty) {
					setText("");
				} else {
					setText(item.getRoomNo());
				}
			}
		});
		
		roomCb.valueProperty().addListener(new ChangeListener<Room>() {
			@Override
			public void changed(ObservableValue<? extends Room> observable, Room oldValue, Room newValue) {
				if(newValue == null) {
					btnOk.setDisable(true);
				}else {
					if(btnOk.isDisable()) btnOk.setDisable(false);
				}	
			}
		});
		
//		DecimalFormat format = new DecimalFormat( "#.0" );
//		depositTextField.setTextFormatter(new TextFormatter<>(c -> {
//			if (c.getControlNewText().isEmpty())
//				return c;
//			ParsePosition parsePosition = new ParsePosition(0);
//			Object object = format.parse(c.getControlNewText(), parsePosition);
//			if (object == null || parsePosition.getIndex() < c.getControlNewText().length())
//				return null;
//			else
//				return c;
//		}));
		depositTextField.setTextFormatter(Comm.getDecimalFormatter());			// 设置只能输入Number
		startTimeSpinner.getEditor().setTextFormatter(Comm.getIntFormatter(6)); // 设置只能输入整数
		daySpinner.getEditor().setTextFormatter(Comm.getIntFormatter(1));
		reserveTimeSpinner.getEditor().setTextFormatter(Comm.getIntFormatter(12));
		phoneTextField.textProperty().addListener(Comm.getNumberTextFieldListener(phoneTextField)); // 设置只能输入数字
		
		// useage in client code
		startTimeSpinner.focusedProperty().addListener((s, ov, nv) -> {
		    if (nv) return;
		    //intuitive method on textField, has no effect, though
		    //spinner.getEditor().commitValue(); 
		    commitEditorText(startTimeSpinner);
		});
		
		daySpinner.focusedProperty().addListener((s, ov, nv) -> {
		    if (nv) return;
		    commitEditorText(daySpinner);
		});
		
		reserveTimeSpinner.focusedProperty().addListener((s, ov, nv) -> {
		    if (nv) return;
		    commitEditorText(reserveTimeSpinner);
		});
	}
	
	/**
	 * c&p from Spinner
	 */
	private <T> void commitEditorText(Spinner<T> spinner) {
	    if (!spinner.isEditable()) return;
	    String text = spinner.getEditor().getText();
	    SpinnerValueFactory<T> valueFactory = spinner.getValueFactory();
	    if (valueFactory != null) {
	        StringConverter<T> converter = valueFactory.getConverter();
	        if (converter != null) {
	            T value = converter.fromString(text);
	            valueFactory.setValue(value);
	        }
	    }
	}
	
	private int findRoomTypeCbIndex(RoomType rt) {
		if(rt == null) return 0;
		ObservableList<RoomType> items = roomTypeCb.getItems();
		RoomType t = null;
		for(int i = 0; i < items.size(); i++) {
			t = items.get(i);
			if(t!= null && rt.getTypeId() == t.getTypeId()) return i;
		}
		return 0;
	}
	
	private int findRoomCbIndex(Room r) {
		if(r == null) return 0;
		ObservableList<Room> items = roomCb.getItems();
		Room t = null;
		for(int i = 0; i < items.size(); i++) {
			t = items.get(i);
			if(t!= null && r.getRoomNo().equals(t.getRoomNo())) return i;
		}
		return 0;
	}
	
	private List<RoomType> runRoomTypeCbFilter(List<RoomType> list) {
		Iterator<RoomType> iter = list.iterator();
		RoomType rt = null;
		while(iter.hasNext()) {
			rt = iter.next();
			if(rt.isHourRoom()) { 		// 钟点房不可以被预定
				iter.remove();			// 将不符合要求的房间类型移除
			}
		}
		return list;
	}
	
	private List<Room> runRoomCbFilter(List<Room> list) {
		Iterator<Room> iter = list.iterator();
		Room room = null;
		while(iter.hasNext()) {
			room = iter.next();
			if(room.getStatus() != 1) { // 状态为可供的房间才可以被预定
				if(roomReserve == null || !roomReserve.getRoomNo().equals(room.getRoomNo())) 
					iter.remove();			// 将不符合要求的房间移除
			}
		}
		return list;
	}
	

	// Event Listener on Button[#btnOk].onAction
	@FXML
	public void onBtnOkAction(ActionEvent event) {
		if(mode == 1) closeWindow(); // 查看模式直接关闭窗口
		Room tRoom = room;
		room = roomCb.getSelectionModel().getSelectedItem();
		if(room == null) return ;
		String name = nameTextField.getText();
		String phone = phoneTextField.getText();
		if(name == null || name.equals("")) {
			MsgBox.showErrorDialog("错误", null, "请填写联系人！");
			return ;
		}
		
		if(phone == null || phone.equals("")) {
			MsgBox.showErrorDialog("错误", null, "请填写联系电话！");
			return ;
		}
		
		// 处理时间
		LocalDate date = startDatePicker.getValue();
		LocalTime time = LocalTime.of(startTimeSpinner.getValue(), 0, 0); // xx:00:00
		LocalDateTime ldt = LocalDateTime.of(date, time);
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		String presetTime = ldt.format(formatter); // 预定时间
		
		LocalDateTime now = LocalDateTime.now();
		String createTime = now.format(formatter); // 创建时间
		
		roomReserve.setPresetTime(presetTime);
		roomReserve.setRoomNo(room.getRoomNo());
		roomReserve.setDuration(daySpinner.getValue());
		roomReserve.setHoldTime(reserveTimeSpinner.getValue());
		roomReserve.setDeposit(Double.parseDouble(depositTextField.getText()));
		roomReserve.setName(name);
		roomReserve.setPhone(phone);
		roomReserve.setCreateTime(createTime);
		roomReserve.setValid(true);
		roomReserve.setComment(commentTextField.getText());
		
		
		if (!tRoom.getRoomNo().equals(room.getRoomNo())) { // 如果更改了房间号
			tRoom.setStatus(1);
			room.setStatus(2);
			if(!HotelDao.update(tRoom) && !HotelDao.update(room)) {
				MsgBox.showInformationDialog("错误", null, "更改房间状态失败！");
				closeWindow();
			}
		}
		roomReserve.setModified(true);
		closeWindow();
	}
	
	// Event Listener on Button[#btnCancel].onAction
	@FXML
	public void onBtnCancelAction(ActionEvent event) {
		closeWindow();
	}
	
	private void closeWindow() {
		Stage stage = (Stage)btnCancel.getScene().getWindow();
		stage.close();
	}
}
